package com.kgis.map.layer {
    import com.kgis.map.Map;
    import com.kgis.map.events.LayerEvent;
    import com.kgis.map.events.MapEvent;
    import com.kgis.map.geometry.basetype.Extent;
    import com.kgis.map.geometry.basetype.Size;
    import com.kgis.map.projection.Projection;
    import flash.display.Sprite;

    /**
     * 图层基类
     */
    public class Layer extends Sprite {
        private var _map:Map = null;
        private var _proxy:String = null;
        private var _loading:Boolean = false;
        protected var _imageSize:Size = null;
        private var _tweenOnZoom:Boolean = false;
        private var _tweenOnLoad:Boolean = false;
        private var _projection:Projection = null;
        private var _id:int;

        /**
         * Layer constructor
         */
        public function Layer(id:int, name:String) {
            this.name = name;
            this.id = id;
            this.visible = true;
            this.doubleClickEnabled = true;
        }

        /**
         * Detroy the map, including removing all event listeners
         */
        public function destroy():void {
            this.removeEventListenerFromMap();
            this.map = null;
        }

        /**
         * Remove map related event listeners
         */
        public function removeEventListenerFromMap():void {
            if (this.map != null) {
                map.removeEventListener(MapEvent.MOVE_END, onMapMove);
                map.removeEventListener(MapEvent.RESIZE, onMapResize);
            }
        }

        /**
         * Set the map where this layer is attached.
         * Here we take care to bring over any of the necessary default properties from the map.
         */
        public function set map(map:Map):void {
            if (this.map != null) {
                removeEventListenerFromMap();
            }

            this._map = map;

            if (this.map) {
                this.map.addEventListener(MapEvent.MOVE_END, onMapMove);
                this.map.addEventListener(MapEvent.RESIZE, onMapResize);
            }

        }

        protected function onMapResize(e:MapEvent):void {
            if (this.visible) {
                this.redraw();
            }
        }

        protected function onMapMove(e:MapEvent):void {
            this.redraw(e.zoomChanged);
        }

        /**
         * Return a reference to the map where belong this layer
         */
        public function get map():Map {
            return this._map;
        }

        /**
         * A Bounds object which represents the location bounds of the current extent display on the map.
         */
        public function get extent():Extent {
            return this.map.extent;
        }

        /**
         * Clear the layer graphics
         */
        public function clear():void {
        }

        /**
         * Reset layer data
         */
        public function reset():void {
        }

        /**
         * Reset layer data
         */
        protected function draw():void {
        }

        /**
         * Is this layer currently displayed ?
         */
        public function get displayed():Boolean {
            return this.visible && this.geoInRange;
        }

        /**
         * Clear and draw, if needed, layer based on current data eventually retreived previously by moveTo function.
         *
         * @param fullRedraw boolean forece the redraw
         */
        public function redraw(fullRedraw:Boolean = true):void {
            this.clear();
            if (this.displayed) {
                this.draw();
            }
        }

        /**
         * Is this layer geometry currently in range, based on its min and max resolutions
         */
        public function get geoInRange():Boolean {
            return true;
        }

        /**
         * Is this layer label currently in range, based on its min and max resolutions
         */
        public function get labelInRange():Boolean {
            return true;
        }

        /**
         * Return layer URL
         */
        public function getURL(bounds:Extent):String {
            return null;
        }

        /**
         * For layers with a gutter, the image is larger than
         * the tile by twice the gutter in each dimension.
         */
        public function get imageSize():Size {
            return this._imageSize;
        }

        public function set imageSize(value:Size):void {
            this._imageSize = value;
        }

        /**
         * 图层在display list里的index
         */
        public function get zindex():int {
            return this.parent.getChildIndex(this);
        }

        public function set zindex(value:int):void {
            this.parent.setChildIndex(this, value);
        }

        /**
         * 代理
         */
        public function get proxy():String {
            if (this._proxy == null && map && map.proxy)
                return map.proxy;
            return this._proxy;
        }

        public function set proxy(value:String):void {
            this._proxy = value;
        }

        /**
         * 可见
         */
        public override function set visible(value:Boolean):void {
            super.visible = value;
            if (this.map != null) {
                this.map.dispatchEvent(new LayerEvent(LayerEvent.LAYER_VISIBLE_CHANGED, this));
            }
        }

        /**
         * 数据是否加载完毕
         */
        public function get loadComplete():Boolean {
            return !this._loading;
        }

        /**
         * 图层加载状态
         */
        protected function set loading(value:Boolean):void {
            if (value == true && this._loading == false && this.map != null) {
                _loading = value;
                this.map.dispatchEvent(new LayerEvent(LayerEvent.LAYER_LOAD_START, this));
            }

            if (value == false && this._loading == true && this.map != null) {
                _loading = value;
                this.map.dispatchEvent(new LayerEvent(LayerEvent.LAYER_LOAD_END, this));
            }
        }

        /**
         * zoom是否使用tween效果
         */
        public function get tweenOnZoom():Boolean {
            return _tweenOnZoom;
        }

        public function set tweenOnZoom(value:Boolean):void {
            _tweenOnZoom = value;
        }

        /**
         * load是否使用tween效果
         */
        public function get tweenOnLoad():Boolean {
            return _tweenOnLoad;
        }

        public function set tweenOnLoad(value:Boolean):void {
            _tweenOnLoad = value;
        }

        public function get projection():Projection {
            return _projection;
        }

        public function set projection(value:Projection):void {
            _projection = value;
        }

        public function get id():int {
            return _id;
        }

        public function set id(value:int):void {
            _id = value;
        }

        public function clone():Layer {
            var layer:Layer = new Layer(this.id, this.name);
            return layer;
        }

    }
}